package com.iring.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.iring.domain.config.prop.LocalConfigProperties;
import com.iring.domain.config.prop.PayPalProperties;
import com.iring.domain.config.prop.PayProperties;
import com.iring.dao.common.AllServicesDao;
import com.iring.dao.common.OperationTypeDao;
import com.iring.dao.common.PayListDao;
import com.iring.dao.common.PayOrderDao;
import com.iring.dao.common.view.CountryViewDao;
import com.iring.domain.common.User;
import com.iring.exception.AuthenticationException;
import com.iring.exception.ParamInvalidException;
import com.iring.interceptor.UserInterceptor;
import com.iring.service.common.AllSuiteService;
import com.iring.service.common.CallLogService;
import com.iring.service.common.CallRateService;
import com.iring.service.common.ConsumptionService;
import com.iring.service.common.CountryViewService;
import com.iring.service.common.DeviceService;
import com.iring.service.common.LocationService;
import com.iring.service.common.LogService;
import com.iring.service.common.OrderService;
import com.iring.service.common.OrderViewService;
import com.iring.service.common.PayReqService;
import com.iring.service.pbx.PbxService;
import com.iring.service.common.SelectService;
import com.iring.service.common.SuiteService;
import com.iring.service.common.UserService;
import com.iring.util.common.CommonUtil;
import com.iring.util.common.DateUtil;
import com.iring.exception.config.ErrorEnum;
import com.iring.util.common.PasswordEncoderUtil;

/**
 * @author wanggan
 */
public abstract class BaseController {

    protected static final String ACCESS_TOKEN = "access_token";
    /**
     * 短信验证session
     */
    public static final String SESSION_PHONE = "phone";

    public static final String SESSION_CODE_PHONE = "code_phone";

    public static final String SESSION_SEND_PHONE = "send_phone";

    public static final String REALIMG_PATH = "./static/userImg/";

    public static final String TEMPORARY_USER = "temporary";

    public static final String RANDOM_IMAGE = "randomImage";

    @Autowired
    protected UserService userService;

    @Autowired
    protected DeviceService deviceService;

    @Autowired
    protected CallLogService callLogService;

    @Autowired
    protected LocationService locationService;

    @Autowired
    protected ConsumptionService consumptionService;

    @Autowired
    protected CallRateService callRateService;

    @Autowired
    protected SuiteService packageService;

    @Autowired
    protected PayReqService payReqService;

    @Autowired
    protected SimpMessagingTemplate simpMessagingTemplate;

    @Autowired
    protected SelectService selectService;

    @Autowired
    protected OperationTypeDao operationTypeDao;

    @Autowired
    protected PayListDao payListDao;

    @Autowired
    protected CountryViewDao countryViewDao;

    @Autowired
    protected AllServicesDao allServicesDao;

    @Autowired
    protected PasswordEncoderUtil passwordEncoder;

    @Autowired
    protected LocalConfigProperties localUserProperties;

    @Autowired
    protected AllSuiteService allSuiteService;

    @Autowired
    protected PbxService pbxService;

    @Autowired
    protected CommonUtil commonUtil;

    @Autowired
    protected PayOrderDao payOrderDao;

    @Autowired
    protected OrderService orderService;

    @Autowired
    protected PayProperties payProperties;

    @Autowired
    protected PayPalProperties payPalProperties;

    @Autowired
    protected OrderViewService orderViewService;

    @Autowired
    protected CountryViewService countryViewService;

    @Autowired
    protected LogService logService;

    /**
     * 获取 HttpServletRequest
     *
     * @return http request对象
     */
    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
    }

    /**
     * 获取用户的真实ip地址
     *
     * @return
     */
    public String getUserRealIp(){
        HttpServletRequest request = getHttpServletRequest();
        return request.getHeader("X-Forwarded-For");
    }

    /**
     * 获取用户的session信息
     *
     * @return {@link User}
     */
    protected User getUserSession() {
        User user = (User) getHttpServletRequest().getSession()
                .getAttribute(UserInterceptor.SESSION_USER);

        if(user instanceof  User){
            return user;
        }
        throw new AuthenticationException(ErrorEnum.USER_NOT_AUTHENTION);
    }

    /**
     * 重新设置用户的session信息
     *
     * @param user
     *            {@link User}
     */
    protected void reSetUserSession(User user) {
        getHttpServletRequest().getSession()
                .setAttribute(UserInterceptor.SESSION_USER, user);
    }

    protected void updateTimeStamp(String sessionKey) {
        HttpSession session = getHttpServletRequest().getSession();
        // 获取session中的时间戳
        Object object = session.getAttribute(sessionKey);
        // 获取当前的时间戳
        long now = DateUtil.getTimestamp();
        if (object != null) {
            long t = Long.valueOf(String.valueOf(object));
            long dis = now - t;
            if (dis > 60 * 1000) {
                // 如果当前时间戳和session中的相差60s,则重新计数,如果没有超过,则忽略
                session.setAttribute(sessionKey, now);
            }
        } else {
            session.setAttribute(sessionKey, now);
        }
    }

    /**
     * 检查pbx的请求头部信息
     *
     * @return  检验请求头结果,true检验通过,false检验失败
     */
    public Boolean checkAuthToken(){
        HttpServletRequest request = getHttpServletRequest();
        String token = request.getHeader("XAuthToken");
        if(null == token){
            throw new ParamInvalidException("invalid authtoken");
        }
        if(passwordEncoder.checkPassword(localUserProperties.getAuthKey(),token)){
            return Boolean.TRUE;
        }else{
            throw new ParamInvalidException("invalid authtoken");
        }
    }

    public Boolean checkAccessToken() {
        HttpServletRequest request = getHttpServletRequest();
        String token = request.getHeader("XAuthToken");
        HttpSession session = request.getSession();
        // 获取access_token
        Object obj = session.getAttribute(ACCESS_TOKEN);
        if (obj != null) {
            String serverToken = obj.toString();
            // 将上传的access_token与session中进行比较
            if (serverToken.equals(token)) {
                return Boolean.TRUE;
            }
        }
        throw new AuthenticationException("invalid auth token");
    }

    private Boolean checkToken(String sessionKey) {
        HttpServletRequest request = getHttpServletRequest();
        String token = request.getHeader("XAuthToken");
        HttpSession session = request.getSession();
        // 获取access_token
        Object obj = session.getAttribute(ACCESS_TOKEN);
        if (obj != null) {
            String serverToken = obj.toString();
            // 将上传的access_token与session中进行比较
            if (serverToken.equals(token)) {
                return isOverTime(sessionKey, session);
            }
        }
        return Boolean.TRUE;

//        HttpServletRequest request = getHttpServletRequest();
//        String token = request.getHeader("XAuthToken");
//        HttpSession session = request.getSession();
//        // 获取access_token
//        Object obj = session.getAttribute(ACCESS_TOKEN);
//        if (obj != null) {
//            String serverToken = obj.toString();
//            // 将上传的access_token与session中进行比较
//            if (serverToken.equals(token)) {
//                // 判断是否操作频繁
//                return isOverTime(sessionKey, session);
//            }
//            throw new ParamInvalidException(ErrorEnum.INVALID_TOKEN);
//        }
//        throw new ParamInvalidException(ErrorEnum.INVALID_TOKEN);

    }

    public void setTemporaryUser(String username){
        HttpSession session = getHttpServletRequest().getSession();
        session.setAttribute(TEMPORARY_USER,username);
    }

    public String getTemporaryUser(){
        HttpSession session = getHttpServletRequest().getSession();
        String username = (String)session.getAttribute(TEMPORARY_USER);
        if(null == username){
            throw new ParamInvalidException(ErrorEnum.INVALID_USERNAME);
        }
        return username;
    }

    public void removeTemporaryUser(){
        HttpSession session = getHttpServletRequest().getSession();
        session.removeAttribute(TEMPORARY_USER);
    }

    public String getRandomImage(){
        HttpSession session = getHttpServletRequest().getSession();
        return (String)session.getAttribute(RANDOM_IMAGE);
    }



    public void checkSessionPhoneToken() {
        checkToken(SESSION_PHONE);
    }

    public void updateSessionPhoneTimeStamp() {
        updateTimeStamp(SESSION_PHONE);
    }

    public void removeSessionPhoneTimeStamp() {
        removeTimeStamp(SESSION_PHONE);
    }

    public void checkSessionCodePhoneToken() {
        checkToken(SESSION_CODE_PHONE);
    }

    public void updateSessionCodePhoneTimeStamp() {
        updateTimeStamp(SESSION_CODE_PHONE);
    }

    public void removeSessionCodePhoneTimeStamp() {
        removeTimeStamp(SESSION_CODE_PHONE);
    }

    public void checkSessionSendPhoneToken() {
        checkToken(SESSION_SEND_PHONE);
    }

    public void updateSessionSendPhoneTimeStamp() {
        updateTimeStamp(SESSION_SEND_PHONE);
    }

    public void removeSessionSendPhoneTimeStamp() {
        removeTimeStamp(SESSION_SEND_PHONE);
    }

    public Boolean isOverTime(String sessionKey, HttpSession session) {
        Object object = session.getAttribute(sessionKey);
        if (object != null) {
            long t = Long.valueOf(String.valueOf(object));
            long dis = DateUtil.getTimestamp() - t;
            if (dis > 60 * 1000) {
                return Boolean.TRUE;
            }
            throw new ParamInvalidException(ErrorEnum.OPT_TOO_MANY_TIMES);
        }
        return Boolean.TRUE;
    }

    /**
     * 移除定时器的时间戳
     *
     * @param key
     *            session键
     */
    public void removeTimeStamp(String key) {
        HttpSession session = getHttpServletRequest().getSession();
        Object object = session.getAttribute(key);
        if (object != null) {
            session.removeAttribute(key);
        }
    }

}
